#include "stdafx.h"
#include "ConfigParser.h"
#include "QueueInterface.h"
#include "Distribution.h"
#include <msclr\marshal_cppstd.h>



using namespace msclr::interop;

ConfigParser::ConfigParser(void)
{
}

map<string, Station*> ConfigParser::parseConfig(string filename) {
	map<string, Station*> stations;
	XmlDocument^ config = gcnew XmlDocument();
	try {
		config->Load(marshal_as<System::String^>(filename));
	}catch(System::IO::FileNotFoundException^) {
		cout<<"Ni ma konfiga"<<endl;
		return stations;
		//@TODO exception
	}

	XmlNodeList^ stationNodes = config->SelectNodes("/config/stations/station");

	XmlNode^ inputNode = config->SelectSingleNode("/config/input");
	stations.insert(xmlToIOStation(inputNode));
	int i = 1;
	for each (XmlNode^ node in stationNodes)
	{
		stations.insert(xmlToStation(node));
	}

	linkStations(stations, config->SelectNodes("/config/links/link"));

	return stations;
}

pair<string, Station*> ConfigParser::xmlToStation(XmlNode^ stationNode) {
	pair<string, Station*> station;
	XmlNode^ queueNode = stationNode->SelectSingleNode("//queue");
	QueueInterface<>* queue = new QueueInterface<>(System::Convert::ToInt32(queueNode->Attributes["type"]->Value), System::Convert::ToInt32(queueNode->Attributes["length"]->Value));
	XmlNode^ distNode = stationNode->SelectSingleNode("//distribution");
	Distribution* dist = new Distribution(System::Convert::ToInt32(distNode->Attributes["type"]->Value),
		System::Convert::ToDouble(distNode->Attributes["param1"]->Value),
		(distNode->Attributes["param2"] == nullptr)?0:System::Convert::ToDouble(distNode->Attributes["param2"]->Value));

	station.first = marshal_as<string>(stationNode->Attributes["name"]->Value);
	station.second = new Station(System::Convert::ToInt32(stationNode->SelectSingleNode("//machines")->Attributes["count"]->Value),dist,queue);
	return station;
}

pair<string, IOStation*> ConfigParser::xmlToIOStation(XmlNode^ inputNode) {
		XmlNode^ distNode = inputNode->SelectSingleNode("./distribution");
	Distribution* dist = new Distribution(System::Convert::ToInt32(distNode->Attributes["type"]->Value),
		System::Convert::ToDouble(distNode->Attributes["param1"]->Value),
		(distNode->Attributes["param2"] == nullptr)?0:System::Convert::ToDouble(distNode->Attributes["param2"]->Value));
	pair<string, IOStation*> station;
		station.first = "io";
		station.second = new IOStation(dist, System::Convert::ToInt32(inputNode->SelectSingleNode("./items")->Attributes["count"]->Value));
	return station;
}

void ConfigParser::linkStations(map<string, Station*> stations, XmlNodeList^ links) {
	for each(XmlNode^ link in links) {
		stations[marshal_as<string>(link->Attributes["from"]->Value)]
			->linkToStation(stations[marshal_as<string>(link->Attributes["to"]->Value)],
				System::Convert::ToDouble(link->Attributes["chance"]->Value));
	}
	for(pair<string,Station*> station: stations) {
		station.second->normalizeLinks();
	}
}
